package com.websocket.utils;

import cn.hutool.json.JSONUtil;
import com.websocket.bean.SocketMsg;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@ServerEndpoint("/web-socket/{userName}")
public class WebSocketUtils {
    private String userName;
    private Session session;

    //固定前缀
    private static final String USER_NAME_PREFIX = "user_name_";

    //用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketUtils> webSocketUtils = new CopyOnWriteArraySet<>();

    //存放Session集合，方便推送消息
    private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();

    //私聊
    public synchronized static void privateMsg(SocketMsg socketMsg) {
        //接收者
        Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
        System.out.println(receiveUser + "     接收者");
        //发送给接收者
        if (receiveUser != null) {
            System.out.println(socketMsg.getSendOutUser() + "向" + socketMsg.getReceiveUser() + "发送了一条:" + socketMsg.getMsg());
            receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser() + ":" + socketMsg.getMsg());
        } else {
            System.out.println(socketMsg.getReceiveUser() + "不在线或者用户不存在");
            //发送消息的用户
            Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser());
            sendOutUser.getAsyncRemote().sendText("系统消息：你发送消息的用户不在线或者不存在");
        }
    }
    //准备
    public synchronized  static void prepare(SocketMsg socketMsg){
        //接收者
        Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
        System.out.println(receiveUser + "     接收者");
        //发送给接收者
//        if (receiveUser != null) {
        System.out.println(socketMsg.getSendOutUser() + "向" + socketMsg.getReceiveUser() + "发送了一条:准备消息" );
        receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":yes-prepare");
//        }
//        else {
//            System.out.println(socketMsg.getReceiveUser() + "不在线或者用户不存在");
//            //发送消息的用户
//            Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser());
//            sendOutUser.getAsyncRemote().sendText("系统消息：你发送消息的用户不在线或者不存在");
//        }
    }
    //取消准备
    public synchronized  static void notprepare(SocketMsg socketMsg){
        //接收者
        Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
        System.out.println(receiveUser + "     接收者");
        //发送给接收者
//        if (receiveUser != null) {
        System.out.println(socketMsg.getSendOutUser() + "向" + socketMsg.getReceiveUser() + "发送了一条:取消准备消息" );
        receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":not-prepare");
//        }
//        else {
//            System.out.println(socketMsg.getReceiveUser() + "不在线或者用户不存在");
//            //发送消息的用户
//            Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser());
//            sendOutUser.getAsyncRemote().sendText("系统消息：你发送消息的用户不在线或者不存在");
//        }
    }
    //刷新后查询准备状态
    public synchronized static void Refreshprepare(SocketMsg socketMsg){
        //接收者
        Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
        System.out.println(receiveUser + "     接收者");
        //发送给接收者
        System.out.println(socketMsg.getSendOutUser() + "向" + socketMsg.getReceiveUser() + "发送了一条:取消准备消息" );
        receiveUser.getAsyncRemote().sendText(socketMsg.getReceiveUser()+":Refresh-prepare");
    }
    //发送当前状态
    public synchronized static void sendprepare(SocketMsg socketMsg){
        //接收者
        Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser());
        System.out.println(receiveUser + "     接收者");
        //发送给接收者
        System.out.println(socketMsg.getSendOutUser() + "向" + socketMsg.getReceiveUser() + "发送了一条:取消准备消息" );
        receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":send-prepare:"+socketMsg.getMsg());
    }


    /**
     * 群聊：公开聊天记录
     *
     * @param userName 发送者的用户名称（当前用户）
     * @param message  发送的消息
     * @param flag     用来标识 是否要将消息推送给 当前用户
     * @author 小青蛙
     * @date 2023/02/01
     */
    public synchronized static void publicMsg(String userName, String message, boolean flag) {
        for (WebSocketUtils item : webSocketUtils) {
            Session session = item.session;
            if (flag) {
                session.getAsyncRemote().sendText(message);
            } else {
                //获取发送这条消息的用户
                Session sendUser = sessionMap.get(USER_NAME_PREFIX + userName);
                //消息不用推送到发送者的客户端
                if (!session.getId().equals(sendUser.getId())) {
                    session.getAsyncRemote().sendText(message);
                }
            }
            System.out.println("公共频道接收到了一条消息" + message);
        }

    }

    /**
     * 监听：连接成功
     *
     * @param session
     * @param userName 连接的用户名
     */
    @OnOpen
    public void OnOpen(Session session, @PathParam("userName") String userName) {
        this.session = session;
        System.out.println(session+"    session");
        this.userName = userName;
        Session session1 = sessionMap.get(USER_NAME_PREFIX + userName);
        if (session1 == null) {
            sessionMap.put(USER_NAME_PREFIX + userName, session);
            webSocketUtils.add(this);
            System.out.println(webSocketUtils);
        }
        //在线数加1
        String sum = userName + "加入聊天室，当前聊天室人数为       " + webSocketUtils.size() + "人";
        System.out.println(sum);
        publicMsg(userName, sum, true);
    }

    /**
     * 监听：收到客户端发送的消息
     *
     * @param message 发送的信息（json格式，里面是 SocketMsg 的信息）
     */
    @OnMessage
    public void OnMessage(String message) {
        System.out.println(JSONUtil.isJsonObj(message)+"         103");
        if (JSONUtil.isJsonObj(message)) {
            SocketMsg socketMsg = JSONUtil.toBean(message, SocketMsg.class);
            switch (socketMsg.getFunction()){
                //聊天
                case "msg-msg":
//                    if (socketMsg.getType() == 1) {
                    //私聊，需要找个发送者和接收者
                    privateMsg(socketMsg);
//                    }
                    break;
                //准备按钮
                case "not-prepare":
                    prepare(socketMsg);
                    break;
                //取消准备
                case "yes-prepare":
                    notprepare(socketMsg);
                    break;
                //查询准备状态
                case "Refresh":
                    Refreshprepare(socketMsg);
                    break;
                //发送当前状态
                case "send-prepare":
                    sendprepare(socketMsg);
                    break;
                default:
                    break;
            }

//            else {
//                //群聊
//                publicMsg(socketMsg.getSendOutUser(), socketMsg.getSendOutUser() + ":" + socketMsg.getMsg(), false);
//            }
        }
    }

    /**
     * 监听: 连接关闭
     */
    @OnClose
    public void OnClose() {
        if (sessionMap.containsKey(USER_NAME_PREFIX + userName)) {
            //连接关闭后，将此websocket从set中删除
            sessionMap.remove(USER_NAME_PREFIX + userName);
            webSocketUtils.remove(this);
        }
        String sum = userName + "退出聊天室，当前聊天室为     " + webSocketUtils.size() + "人";
        System.out.println(sum);
        publicMsg(userName, sum, true);
    }

    /**
     * 监听：发生异常
     *
     * @param error
     */
    @OnError
    public void onError(Throwable error) {
        System.out.println("userName为：" + userName + "，发生错误：" + error.getMessage());
        error.printStackTrace();
    }
}
